﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Text;
using Microsoft.SqlServer.Dts.Pipeline;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using MouldingAndMillwork;

namespace MouldingAndMillwork.SSIS
{
    public partial class SSISUtility
    {
        #region CLASS: DataTypeInformation
        public class DataTypeInformation
        {
            public static string BuildDescription(ColumnInformation columnInformation)
            {
                return DataTypeInformation.BuildDescription(columnInformation.DataType, columnInformation.LineageID, columnInformation.Scale, columnInformation.Precision, columnInformation.CodePage);
            }

            public static string BuildDescription(IDTSOutputColumn100 outputColumn)
            {
                return DataTypeInformation.BuildDescription(outputColumn.DataType, outputColumn.LineageID, outputColumn.Scale, outputColumn.Precision, outputColumn.CodePage);
            }

            public static string BuildDescription(DataType dataType, int length, int scale, int precision, int codePage)
            {
                string description_pt1;
                string description_pt2 = null;

                switch (dataType)
                {
                    case DataType.DT_BOOL:
                        description_pt1 = "Boolean";
                        break;

                    case DataType.DT_BYTES:
                        description_pt1 = "Byte stream";
                        description_pt2 = "Length: " + length.ToString();
                        break;

                    case DataType.DT_CY:
                        description_pt1 = "Currency";
                        break;

                    case DataType.DT_DATE:
                        description_pt1 = "Date";
                        break;

                    case DataType.DT_DBDATE:
                        description_pt1 = "Database date";
                        break;

                    case DataType.DT_DBTIME:
                        description_pt1 = "Database time";
                        break;

                    case DataType.DT_DBTIME2:
                        description_pt1 = "Database time with precision";
                        description_pt2 = "Scale: " + scale.ToString();
                        break;

                    case DataType.DT_DBTIMESTAMP:
                        description_pt1 = "Database timestamp";
                        break;

                    case DataType.DT_DBTIMESTAMP2:
                        description_pt1 = "Database timestamp with precision";
                        description_pt2 = "Scale: " + scale.ToString();
                        break;

                    case DataType.DT_DBTIMESTAMPOFFSET:
                        description_pt1 = "Database timestamp with timezone";
                        description_pt2 = "Scale: " + scale.ToString();
                        break;

                    case DataType.DT_DECIMAL:
                        description_pt1 = "Decimal";
                        description_pt2 = "Scale: " + scale.ToString();
                        break;

                    case DataType.DT_EMPTY:
                        description_pt1 = "Empty";
                        break;

                    case DataType.DT_FILETIME:
                        description_pt1 = "File timestamp";
                        break;

                    case DataType.DT_GUID:
                        description_pt1 = "Unique identifier";
                        break;

                    case DataType.DT_I1:
                        description_pt1 = "Single-byte signed integer";
                        break;

                    case DataType.DT_I2:
                        description_pt1 = "Two-byte signed integer";
                        break;

                    case DataType.DT_I4:
                        description_pt1 = "Four-byte signed integer";
                        break;

                    case DataType.DT_I8:
                        description_pt1 = "Eight-byte signed integer";
                        break;

                    case DataType.DT_IMAGE:
                        description_pt1 = "Image";
                        break;

                    case DataType.DT_NTEXT:
                        description_pt1 = "Unicode text stream";
                        break;

                    case DataType.DT_NUMERIC:
                        description_pt1 = "Numeric";
                        description_pt2 = "Scale: " + scale.ToString() + "\n"
                            + "Precision: " + precision.ToString();
                        break;

                    case DataType.DT_R4:
                        description_pt1 = "Float";
                        break;

                    case DataType.DT_R8:
                        description_pt1 = "Double-precision float";
                        break;

                    case DataType.DT_STR:
                        description_pt1 = "String";
                        description_pt2 = "Length: " + length.ToString() + "\n"
                            + "Code Page: " + codePage.ToString() ;
                        switch (codePage)
                        {
                            case 1250:
                                description_pt2 += " (Central Europe)";
                                break;

                            case 1251:
                                description_pt2 += " (Cyrillic)";
                                break;

                            case 1252:
                                description_pt2 += " (Latin I)";
                                break;

                            case 1253:
                                description_pt2 += " (Greek)";
                                break;

                            case 1254:
                                description_pt2 += " (Turkish)";
                                break;

                            case 1255:
                                description_pt2 += " (Hebrew)";
                                break;

                            case 1256:
                                description_pt2 += " (Arabic)";
                                break;

                            case 1257:
                                description_pt2 += " (Baltic)";
                                break;

                            case 1258:
                                description_pt2 += " (Vietnam)";
                                break;

                            case 874:
                                description_pt2 += " (Thai)";
                                break;

                            case 932:
                                description_pt2 += " (Japanese Shift-JIS)";
                                break;

                            case 936:
                                description_pt2 += " (Simplified Chinese GBK)";
                                break;

                            case 949:
                                description_pt2 += " (Korean)";
                                break;

                            case 950:
                                description_pt2 += " (Traditional Chinese Big5)";
                                break;
                        }
                        break;

                    case DataType.DT_TEXT:
                        description_pt1 = "Text stream";
                        break;

                    case DataType.DT_UI1:
                        description_pt1 = "Single-byte unsigned integer";
                        break;

                    case DataType.DT_UI2:
                        description_pt1 = "Two-byte unsigned integer";
                        break;

                    case DataType.DT_UI4:
                        description_pt1 = "Four-byte unsigned integer";
                        break;

                    case DataType.DT_UI8:
                        description_pt1 = "Eight-byte unsigned integer";
                        break;

                    case DataType.DT_WSTR:
                        description_pt1 = "Unicode string";
                        description_pt2 = "Length: " + length.ToString();
                        break;

                    default:
                        description_pt1 = "unknown";
                        break;
                }

                description_pt1 ="Data type: " + description_pt1 + " [" + dataType.ToString() + "]";

                if (description_pt2 != null)
                {
                    return description_pt1 + "\n" + description_pt2;
                }
                else
                {
                    return description_pt1;
                }
            }
        }
        #endregion

        #region CLASS: DataTypeList
        public class DataTypeList
        {
            public static readonly DataTypeList All;
            public static readonly DataTypeList IntegralValued;
            public static readonly DataTypeList DateValued;
            public static readonly DataTypeList BooleanValued;
            public static readonly DataTypeList StringValued;

            #region Class Initializer
            static DataTypeList()
            {
                DataTypeList.All = new DataTypeList();
                DataTypeList.IntegralValued = new DataTypeList();
                DataTypeList.DateValued = new DataTypeList();
                DataTypeList.BooleanValued = new DataTypeList();
                DataTypeList.StringValued = new DataTypeList();
                foreach (DataType dataType in Enum.GetValues(typeof(DataType)))
                {
                    DataTypeList.All.Add(dataType);

                    if (dataType.ToString().Contains("DT_I") || dataType.ToString().Contains("DT_UI"))
                    {
                        DataTypeList.IntegralValued.Add(dataType);
                    }

                    if ((dataType.ToString().Contains("DATE") || dataType.ToString().Contains("TIME"))
                        && (!dataType.ToString().Contains("BYREF")))
                    {
                        DataTypeList.DateValued.Add(dataType);
                    }

                    if (dataType == DataType.DT_BOOL)
                    {
                        DataTypeList.BooleanValued.Add(dataType);
                    }

                    if ((dataType == DataType.DT_STR) 
                        || (dataType == DataType.DT_WSTR)
                        || (dataType == DataType.DT_NTEXT)
                        || (dataType == DataType.DT_TEXT))
                    {
                        DataTypeList.StringValued.Add(dataType);
                    }
                }
            }
            #endregion

            #region Private Variables
            private readonly List<DataType> _list;
            #endregion

            #region Constructors
            private DataTypeList()
            {
                this._list = new List<DataType>();
            }

            public DataTypeList(DataType[] dataTypes)
            {
                this._list = new List<DataType>();
                foreach (DataType dataType in dataTypes)
                {
                    this._list.Add(dataType);
                }
            }

            public DataTypeList(List<DataType> dataTypes)
            {
                this._list = new List<DataType>(dataTypes);
            }
            #endregion

            #region Properties
            private void Add(DataType dataType)
            {
                this._list.Add(dataType);
            }

            public bool Contains(DataType dataType)
            {
                foreach (DataType containedType in this._list)
                {
                    if (dataType == containedType)
                    {
                        return true;
                    }
                }

                return false;
            }

            public int Count
            {
                get { return this._list.Count; }
            }

            public DataType this[int index]
            {
                get { return this._list[index]; }
            }
            #endregion

            #region Methods
            public DataTypeList Union(DataTypeList otherList)
            {
                DataTypeList newList = new DataTypeList(this._list);

                newList._list.AddRange(otherList._list);

                return newList;
            }
            #endregion
        }
        #endregion

        #region CLASS: DataTypeComparer
        public class DataTypeComparer
        {
            #region DataType comparison between System and SSIS
            public enum CompareDataTypesStrictness
            {
                /// <summary>All type information given must match exactly</summary>
                Strict,
                /// <summary>Type information given must be a superset of what's being compared (i.e. string length of definition is longer than string being compared)</summary>
                Superset,
                /// <summary>Types that will match when converted to text SQL statements</summary>
                Loose
            }

            public static int CompareDataTypes(DataRow schemaColumn, DataType dataType, int length, int precision, int scale,
                CompareDataTypesStrictness strictness, out string compareProblem)
            {
                if (schemaColumn == null)
                {
                    compareProblem = "column doesn't exist.";
                    return -1;
                }

                DataType dataType1 = (DataType)schemaColumn["DataType"];
                int length1 = (int)schemaColumn["CharacterLength"];
                int precision1 = 0;
                int scale1 = 0;
                int codePage1 = 0;
                if (dataType1 == DataType.DT_STR)
                {
                    codePage1 = (int)schemaColumn["NumericScale"];
                }
                else
                {
                    precision1 = (int)schemaColumn["NumericPrecision"];
                    scale1 = (int)schemaColumn["NumericScale"];
                }

                return DataTypeComparer.CompareDataTypes(dataType1, length1, precision1, scale1, 0,
                    dataType, length, precision, scale, 0,
                    strictness, out compareProblem);
            }

            public static int CompareDataTypes(IDTSVirtualInputColumn100 inputOne, IDTSVirtualInputColumn100 inputTwo,
                CompareDataTypesStrictness strictness, out string compareProblem)
            {
                if ((inputOne == null) || (inputTwo == null))
                {
                    compareProblem = "column doesn't exist.";
                    return -1;
                }

                return DataTypeComparer.CompareDataTypes(inputOne.DataType, inputOne.Length, inputOne.Precision, inputOne.Scale, inputOne.CodePage,
                    inputTwo.DataType, inputTwo.Length, inputTwo.Precision, inputTwo.Scale, inputTwo.CodePage,
                    strictness, out compareProblem);
            }

            public static int CompareDataTypes(IDTSVirtualInputColumn100 vColumn, DataType dataType, int length,
                CompareDataTypesStrictness strictness, out string compareProblem)
            {
                if (vColumn == null)
                {
                    compareProblem = "column doesn't exist.";
                    return -1;
                }

                return DataTypeComparer.CompareDataTypes(vColumn.DataType, vColumn.Length,
                    dataType, length,
                    strictness, out compareProblem);
            }

            public static int CompareDataTypes(IDTSVirtualInputColumn100 vColumn, DataType dataType, int length, int precision, int scale, int codePage,
                CompareDataTypesStrictness strictness, out string compareProblem)
            {
                if (vColumn == null)
                {
                    compareProblem = "column doesn't exist.";
                    return -1;
                }

                return DataTypeComparer.CompareDataTypes(vColumn.DataType, vColumn.Length, vColumn.Precision, vColumn.Scale, vColumn.CodePage,
                    dataType, length, precision, scale, codePage,
                    strictness, out compareProblem);
            }

            public static int CompareDataTypes(ColumnInformation columnInformation1, IDTSOutputColumn100 columnInformation2,
                CompareDataTypesStrictness strictness, out string compareProblem)
            {
                return DataTypeComparer.CompareDataTypes(columnInformation1.DataType, columnInformation1.Length,columnInformation1.Precision, 
                    columnInformation1.Scale, columnInformation1.CodePage, columnInformation2.DataType, columnInformation2.Length,
                    columnInformation2.Precision, columnInformation2.Scale, columnInformation2.CodePage,
                    strictness, out compareProblem);
            }

            public static int CompareDataTypes(DataType dataType1, int length1, DataType dataType2, int length2,
                CompareDataTypesStrictness strictness, out string compareProblem)
            {
                return DataTypeComparer.CompareDataTypes(dataType1, length1, 0, 0, 0, dataType2, length2, 0, 0, 0, strictness, out compareProblem);
            }

            public static int CompareDataTypes(DataType dataType1, int length1, int precision1, int scale1, int codePage1,
                DataType dataType2, int length2, int precision2, int scale2, int codePage2,
                CompareDataTypesStrictness strictness, out string compareProblem)
            {
                int compare = 0;
                compareProblem = "";

                compare = dataType1.CompareTo(dataType2);
                if (compare != 0)
                {
                    if (strictness == CompareDataTypesStrictness.Loose)
                    {
                        if (((dataType1 == DataType.DT_STR) || (dataType1 == DataType.DT_WSTR))
                            && ((dataType2 == DataType.DT_STR) || (dataType2 == DataType.DT_WSTR)))
                        {
                            compare = 0;
                        }
                        else if (((dataType1 == DataType.DT_DECIMAL) || (dataType1 == DataType.DT_NUMERIC))
                            && ((dataType2 == DataType.DT_DECIMAL) || (dataType2 == DataType.DT_NUMERIC)))
                        {
                            compare = 0;
                        }
                    }
                    if (compare != 0)
                    {
                        compareProblem = "Type is " + dataType1.ToString() + " not " + dataType2.ToString();
                    }
                }
                if (compare == 0)
                {
                    compare = length1.CompareTo(length2);
                    if (compare != 0)
                    {
                        if (strictness == CompareDataTypesStrictness.Strict)
                        {
                            compareProblem = "Length is " + length1.ToString() + " not " + length2.ToString();
                        }
                        else
                        {
                            if (length1 > length2)
                            {
                                compare = 0;
                            }
                            else
                            {
                                compareProblem = "Length should be " + length1.ToString() + " or shorter, not " + length2.ToString();
                            }
                        }
                    }
                }
                if (compare == 0)
                {
                    compare = precision1.CompareTo(precision2);
                    if (compare != 0)
                    {
                        compareProblem = "Precision is " + precision1.ToString() + " not " + precision2.ToString();
                    }
                }
                if (compare == 0)
                {
                    compare = scale1.CompareTo(scale2);
                    if (compare != 0)
                    {
                        compareProblem = "Scale is " + scale1.ToString() + " not " + scale2.ToString();
                    }
                }
                if (compare == 0)
                {
                    compare = codePage1.CompareTo(codePage2);
                    if (compare != 0)
                    {
                        compareProblem = "Code page is " + codePage1.ToString() + " not " + codePage2.ToString();
                    }
                }

                return compare;
            }

            #region CompareFields
            public static int CompareFields(DataType type, object fieldOne, object fieldTwo,
                bool ignoreLeadingAndTrailingSpaces, bool ignoreCase, CultureInfo culture)
            {
                if ((fieldOne == null) && (fieldTwo == null))
                {
                    return 0;
                }
                else if (fieldOne == null)
                {
                    return -1;
                }
                else if (fieldTwo == null)
                {
                    return 1;
                }
                else
                {
                    try
                    {
                        System.Type fieldOneType = fieldOne.GetType();
                        System.Type fieldTwoType = fieldTwo.GetType();
                        switch (type)
                        {
                            #region Boolean
                            case DataType.DT_BOOL:
                                bool boolOne;
                                bool boolTwo;
                                if (fieldOneType == typeof(bool))
                                {
                                    boolOne = (bool)fieldOne;
                                }
                                else
                                {
                                    boolOne = Convert.ToBoolean(fieldOne);
                                }
                                if (fieldTwoType == typeof(bool))
                                {
                                    boolTwo = (bool)fieldTwo;
                                }
                                else
                                {
                                    boolTwo = Convert.ToBoolean(fieldTwo);
                                }
                                return boolOne.CompareTo(boolTwo);
                            #endregion
                            #region Decimal types (Currency, Decimal, Numeric)
                            case DataType.DT_CY:
                            case DataType.DT_DECIMAL:
                            case DataType.DT_NUMERIC:
                                decimal decimalOne;
                                decimal decimalTwo;
                                if (fieldOneType == typeof(decimal))
                                {
                                    decimalOne = (decimal)fieldOne;
                                }
                                else
                                {
                                    decimalOne = Convert.ToDecimal(fieldOne);
                                }
                                if (fieldTwoType == typeof(decimal))
                                {
                                    decimalTwo = (decimal)fieldTwo;
                                }
                                else
                                {
                                    decimalTwo = Convert.ToDecimal(fieldTwo);
                                }
                                return decimalOne.CompareTo(decimalTwo);
                            #endregion
                            #region Date types (Date, DBDate, DBTime, DBTimeStamp
                            case DataType.DT_DATE:
                            case DataType.DT_DBDATE:
                            case DataType.DT_DBTIME:
                            case DataType.DT_DBTIMESTAMP:
                            case DataType.DT_DBTIMESTAMP2:
                            case DataType.DT_DBTIME2:
                                DateTime dateOne;
                                DateTime dateTwo;
                                if (fieldOneType == typeof(DateTime))
                                {
                                    dateOne = (DateTime)fieldOne;
                                }
                                else
                                {
                                    dateOne = Convert.ToDateTime(fieldOne);
                                }
                                if (fieldTwoType == typeof(DateTime))
                                {
                                    dateTwo = (DateTime)fieldTwo;
                                }
                                else
                                {
                                    dateTwo = Convert.ToDateTime(fieldTwo);
                                }
                                return dateOne.CompareTo(dateTwo);
                            #endregion
                            #region Eight-Byte Unsigned Integer types (FileTime, UI8)
                            case DataType.DT_FILETIME:
                            case DataType.DT_UI8:
                                UInt64 uint64One;
                                UInt64 uint64Two;
                                if (fieldOneType == typeof(UInt64))
                                {
                                    uint64One = (UInt64)fieldOne;
                                }
                                else
                                {
                                    uint64One = Convert.ToUInt64(fieldOne);
                                }
                                if (fieldTwoType == typeof(UInt64))
                                {
                                    uint64Two = (UInt64)fieldTwo;
                                }
                                else
                                {
                                    uint64Two = Convert.ToUInt64(fieldTwo);
                                }
                                return uint64One.CompareTo(uint64Two);
                            #endregion
                            #region GUIDs
                            case DataType.DT_GUID:
                                Guid guidOne = (Guid)fieldOne;
                                Guid guidTwo = (Guid)fieldTwo;
                                System.Data.SqlTypes.SqlGuid sqlGuidOne = new System.Data.SqlTypes.SqlGuid(guidOne);
                                System.Data.SqlTypes.SqlGuid sqlGuidTwo = new System.Data.SqlTypes.SqlGuid(guidTwo);
                                return sqlGuidOne.CompareTo(sqlGuidTwo);
                            #endregion
                            #region Single-Byte Integer types (I1, UI1)
                            case DataType.DT_I1:
                            case DataType.DT_UI1:
                                byte byteOne;
                                byte byteTwo;
                                if (fieldOneType == typeof(byte))
                                {
                                    byteOne = (byte)fieldOne;
                                }
                                else
                                {
                                    byteOne = Convert.ToByte(fieldOne);
                                }
                                if (fieldTwoType == typeof(byte))
                                {
                                    byteTwo = (byte)fieldTwo;
                                }
                                else
                                {
                                    byteTwo = Convert.ToByte(fieldTwo);
                                }
                                return byteOne.CompareTo(byteTwo);
                            #endregion
                            #region Two-Byte Signed Integer Types
                            case DataType.DT_I2:
                                Int16 int16One;
                                Int16 int16Two;
                                if (fieldOneType == typeof(Int16))
                                {
                                    int16One = (Int16)fieldOne;
                                }
                                else
                                {
                                    int16One = Convert.ToInt16(fieldOne);
                                }
                                if (fieldTwoType == typeof(Int16))
                                {
                                    int16Two = (Int16)fieldTwo;
                                }
                                else
                                {
                                    int16Two = Convert.ToInt16(fieldTwo);
                                }
                                return int16One.CompareTo(int16Two);
                            #endregion
                            #region Four-Byte Signed Integers
                            case DataType.DT_I4:
                                Int32 int32One;
                                Int32 int32Two;
                                if (fieldOneType == typeof(Int32))
                                {
                                    int32One = (Int32)fieldOne;
                                }
                                else
                                {
                                    int32One = Convert.ToInt32(fieldOne);
                                }
                                if (fieldTwoType == typeof(Int32))
                                {
                                    int32Two = (Int32)fieldTwo;
                                }
                                else
                                {
                                    int32Two = Convert.ToInt32(fieldTwo);
                                }
                                return int32One.CompareTo(int32Two);
                            #endregion
                            #region Eight-Byte Signed Integer types
                            case DataType.DT_I8:
                                Int64 int64One;
                                Int64 int64Two;
                                if (fieldOneType == typeof(Int64))
                                {
                                    int64One = (Int64)fieldOne;
                                }
                                else
                                {
                                    int64One = Convert.ToInt64(fieldOne);
                                }
                                if (fieldTwoType == typeof(Int64))
                                {
                                    int64Two = (Int64)fieldTwo;
                                }
                                else
                                {
                                    int64Two = Convert.ToInt64(fieldTwo);
                                }
                                return int64One.CompareTo(int64Two);
                            #endregion
                            #region Byte Arrays (Bytes and Image)
                            case DataType.DT_BYTES:
                            case DataType.DT_IMAGE:
                            case DataType.DT_NTEXT:
                            case DataType.DT_TEXT:
                                byte[] byteArrayOne = (byte[])fieldOne;
                                byte[] byteArrayTwo = (byte[])fieldTwo;

                                if (byteArrayOne.Length != byteArrayTwo.Length)
                                {
                                    return byteArrayOne.Length.CompareTo(byteArrayTwo.Length);
                                }
                                else
                                {
                                    int compare = 0;
                                    for (int i = 0; i < byteArrayOne.Length; i++)
                                    {
                                        compare = byteArrayOne[i].CompareTo(byteArrayTwo[i]);
                                        if (compare != 0)
                                        {
                                            return compare;
                                        }
                                    }
                                    return 0;
                                }
                            #endregion
                            #region Four-Byte Floating Point
                            case DataType.DT_R4:
                                float floatOne;
                                float floatTwo;
                                if (fieldOneType == typeof(float))
                                {
                                    floatOne = (float)fieldOne;
                                }
                                else
                                {
                                    floatOne = Convert.ToSingle(fieldOne);
                                }
                                if (fieldTwoType == typeof(float))
                                {
                                    floatTwo = (float)fieldTwo;
                                }
                                else
                                {
                                    floatTwo = Convert.ToSingle(fieldTwo);
                                }
                                return floatOne.CompareTo(floatTwo);
                            #endregion
                            #region Eight-Byte Floating Point
                            case DataType.DT_R8:
                                double doubleOne;
                                double doubleTwo;
                                if (fieldOneType == typeof(double))
                                {
                                    doubleOne = (double)fieldOne;
                                }
                                else
                                {
                                    doubleOne = Convert.ToDouble(fieldOne);
                                }
                                if (fieldTwoType == typeof(double))
                                {
                                    doubleTwo = (double)fieldTwo;
                                }
                                else
                                {
                                    doubleTwo = Convert.ToDouble(fieldTwo);
                                }
                                return doubleOne.CompareTo(doubleTwo);
                            #endregion
                            #region Two-Byte Unsigned Integers
                            case DataType.DT_UI2:
                                UInt16 uint16One;
                                UInt16 uint16Two;
                                if (fieldOneType == typeof(UInt16))
                                {
                                    uint16One = (UInt16)fieldOne;
                                }
                                else
                                {
                                    uint16One = Convert.ToUInt16(fieldOne);
                                }
                                if (fieldTwoType == typeof(UInt16))
                                {
                                    uint16Two = (UInt16)fieldTwo;
                                }
                                else
                                {
                                    uint16Two = Convert.ToUInt16(fieldTwo);
                                }
                                return uint16One.CompareTo(uint16Two);
                            #endregion
                            #region Four-Byte Unsigned Integers
                            case DataType.DT_UI4:
                                UInt32 uint32One;
                                UInt32 uint32Two;
                                if (fieldOneType == typeof(UInt32))
                                {
                                    uint32One = (UInt32)fieldOne;
                                }
                                else
                                {
                                    uint32One = Convert.ToUInt32(fieldOne);
                                }
                                if (fieldTwoType == typeof(UInt32))
                                {
                                    uint32Two = (UInt32)fieldTwo;
                                }
                                else
                                {
                                    uint32Two = Convert.ToUInt32(fieldTwo);
                                }
                                return uint32One.CompareTo(uint32Two);
                            #endregion
                            #region Strings
                            case DataType.DT_WSTR:
                            case DataType.DT_STR:
                                string stringOne = (string)fieldOne;
                                string stringTwo = (string)fieldTwo;
                                if (ignoreLeadingAndTrailingSpaces)
                                {
                                    stringOne = stringOne.Trim();
                                    stringTwo = stringTwo.Trim();
                                }
                                return String.Compare(stringOne, stringTwo, ignoreCase, culture);
                            #endregion
                            default:
                                throw new ArgumentException("Unsupported Data Type for comparison: " + type.ToString());
                        }
                    }
                    #region catch ...
                    catch (Exception ex)
                    {
                        if (System.Diagnostics.Debugger.IsAttached)
                        {
                            System.Diagnostics.Debugger.Break();
                        }
                        throw ex;
                    }
                    #endregion
                }
            }
            #endregion
            #endregion
        }
        #endregion
    }
}
